package cn.panshi.cdcdemo;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;

import cn.panshi.mongocdc.BizRouterAnnotation;
import cn.panshi.mongocdc.CdcTtlTaskDoc;
import cn.panshi.mongocdc.IMongoCdcTtlTaskRouter;
import cn.panshi.mongocdc.ReflectionUtils;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@SuppressWarnings({ "rawtypes", "unchecked" })
@Component
public class MongoCdcTtlTaskRouter implements IMongoCdcTtlTaskRouter {
	private @Resource MongoTemplate mongoTemplate;

	public enum TTL_TASK_TYPE {
		Test, //
		loginSuccessNotify,//
		;
	}

	@BizRouterAnnotation(enumClazz = TTL_TASK_TYPE.class, enumValue = "loginSuccessNotify")
	private String loginSuccessNotify(CdcTtlTaskDoc task) {
		log.debug(task + "");

		return "success";
	}

	@BizRouterAnnotation(enumClazz = TTL_TASK_TYPE.class, enumValue = "Test")
	private String testTaskExecute(CdcTtlTaskDoc task) {
		log.debug(task + "");

		return "success";
	}

	@Override
	public final Serializable execute(CdcTtlTaskDoc task) {
		TTL_TASK_TYPE type = TTL_TASK_TYPE.valueOf(task.getType());

		Method matchedFunc = this.matchBizMethodByCdc(type);
		if (matchedFunc == null) {
			throw new RuntimeException("No biz metched 4 cdc " + type.name());
		}

		try {
			return (Serializable) matchedFunc.invoke(this, task);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	private Method matchBizMethodByCdc(Enum taskType) {
		List<Method> methodsWithAnnotation = ReflectionUtils.getMethodWithAnnotation(this.getClass(),
				BizRouterAnnotation.class);

		List<Object> matchedMethods = new ArrayList<>();
		methodsWithAnnotation.stream().filter(m -> {
			BizRouterAnnotation ann = m.getAnnotation(BizRouterAnnotation.class);
			Class<? extends Enum> annType = ann.enumClazz();
			String annValue = ann.enumValue();
			Enum annTypeEnum = Enum.valueOf(annType, annValue);
			return annTypeEnum == taskType;
		}).forEach(each -> matchedMethods.add(each));

		if (matchedMethods.isEmpty()) {
			log.error("No method found with MongoCdcBizAnnotation(" + taskType.name() + ")");
			return null;
		} else {
			return (Method) matchedMethods.get(0);
		}
	}

}